package com.sojson.service.impl;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.ijpay.core.IJPayHttpResponse;
import com.ijpay.core.enums.RequestMethod;
import com.ijpay.wxpay.WxPayApi;
import com.ijpay.wxpay.enums.WxApiType;
import com.ijpay.wxpay.enums.WxDomain;
import com.sojson.config.exception.TransException;
import com.sojson.constant.Lock;
import com.sojson.dao.OrderChildDao;
import com.sojson.dao.OrderDao;
import com.sojson.entity.po.Order;
import com.sojson.entity.po.OrderChild;
import com.sojson.enums.EOrderChildStatus;
import com.sojson.enums.core.EOrderStatus;
import com.sojson.enums.core.EPayStatus;
import com.sojson.enums.core.ERefundsStatus;
import com.sojson.service.OrderChildService;
import com.sojson.util.ArithUtil;
import com.sojson.util.StringUtil;
import com.sojson.util.SystemParamUtil;
import com.sojson.util.id.GUIDUtil;
import com.sojson.util.json.JsonUtil;
import com.sojson.util.pay.wx.WxUtil;
import com.sojson.util.pay.wx.bean.WxParamV3;
import com.sojson.util.pay.wx.bean.WxResponseV3;
import com.sojson.util.pay.wx.bean.child.param.WxPamAmount;
import com.sojson.util.pay.wx.constant.WxConstant;
import com.sojson.util.pay.wx.constant.WxCurrencyType;

/**
 * 子订单表Service实现类
 * 
 * @author liu
 * @date 2021-04-07
 */
@Service
public class OrderChildServiceImpl implements OrderChildService {

    @Autowired
    private OrderChildServiceImpl orderChildServiceImpl;
    @Resource
    private OrderChildDao orderChildDaoImpl;
    @Resource
    private OrderDao orderDaoImpl;

    /**
     * 单条插入
     * 
     * @param orderChild
     * @return
     * @throws SQLException
     */
    @Override
    public int insert(OrderChild orderChild) {
        int insert = orderChildDaoImpl.insert(orderChild);
        return insert;
    }

    /**
     * 批量插入
     * 
     * @param orderChild
     * @return
     * @throws SQLException
     */
    @Override
    public int insertList(OrderChild orderChild) {
        int insertList = orderChildDaoImpl.insertList(orderChild.getOrderChilds());
        return insertList;
    }

    /**
     * 通过对象批量删除(物理删除)
     * 
     * @param orderChild
     * @return
     * @throws SQLException
     */
    @Override
    public int deleteByDto(OrderChild orderChild) {
        int deleteByDto = orderChildDaoImpl.deleteByDto(orderChild);
        return deleteByDto;
    }

    /**
     * 统计全部数量
     * 
     * @return
     * @throws SQLException
     */
    @Override
    public int countAll() {
        int countAll = orderChildDaoImpl.countAll();
        return countAll;
    }

    /**
     * 查询所有
     * 
     * @return
     * @throws SQLException
     */
    @Override
    public List<OrderChild> findAll() {
        List<OrderChild> findAll = orderChildDaoImpl.listAll();
        return findAll;
    }

    /**
     * 根据对象统计数量
     * 
     * @param orderChild
     * @return
     * @throws SQLException
     */
    @Override
    public int countByDto(OrderChild orderChild) {
        int countByDto = orderChildDaoImpl.countByDto(orderChild);
        return countByDto;
    }

    /**
     * 根据对象查询
     * 
     * @param orderChild
     * @return
     * @throws SQLException
     */
    @Override
    public List<OrderChild> findByDto(OrderChild orderChild) {
        List<OrderChild> findByDto = orderChildDaoImpl.listByDto(orderChild);
        return findByDto;
    }

    /**
     * 通过id删除(物理删除)
     * 
     * @param id
     * @return
     * @throws SQLException
     */
    @Override
    public int deleteById(Integer id) {
        int deleteById = orderChildDaoImpl.deleteById(id);
        return deleteById;
    }

    /**
     * 通过id列表删除(物理删除)
     * 
     * @param ids
     * @return
     * @throws SQLException
     */
    @Override
    public int deleteByIdList(ArrayList<Integer> ids) {
        int deleteByIdList = orderChildDaoImpl.deleteByIdList(ids);
        return deleteByIdList;
    }

    /**
     * 通过id更新(全部更新)
     * 
     * @param orderChild
     * @return
     * @throws SQLException
     */
    @Override
    public int updateById(OrderChild orderChild) {
        int updateById = orderChildDaoImpl.updateById(orderChild);
        return updateById;
    }

    /**
     * 通过id列表更新(全部更新)(更新内容相同)
     * 
     * @param orderChild
     * @return
     * @throws SQLException
     */
    @Override
    public int updateStaticByIdList(OrderChild orderChild) {
        int updateStaticByIdList = orderChildDaoImpl.updateStaticByIdList(orderChild);
        return updateStaticByIdList;
    }

    /**
     * 通过id列表更新(全部更新)(更新内容不相同)
     * 
     * @param orderChild
     * @return
     * @throws SQLException
     */
    @Override
    public int updateChangeByIdList(OrderChild orderChild) {
        int updateChangeByIdList = orderChildDaoImpl.updateChangeByIdList(orderChild.getOrderChilds());
        return updateChangeByIdList;
    }

    /**
     * 通过id更新(局部更新)
     * 
     * @param orderChild
     * @return
     * @throws SQLException
     */
    @Override
    public int updatePartialById(OrderChild orderChild) {
        int updatePartialById = orderChildDaoImpl.updatePartialById(orderChild);
        return updatePartialById;
    }

    /**
     * 通过订单号更新(局部更新)
     * 
     * @param orderChild
     * @return
     */
    @Override
    public int updatePartialByOrderNo(OrderChild orderChild) {
        int updatePartialByOrderNo = orderChildDaoImpl.updatePartialByOrderNo(orderChild);
        return updatePartialByOrderNo;
    }

    /**
     * 通过id列表更新(局部更新)(更新内容相同)
     * 
     * @param orderChild
     * @return
     * @throws SQLException
     */
    @Override
    public int updateStaticPartialByIdList(OrderChild orderChild) {
        int updateStaticPartialByIdList = orderChildDaoImpl.updateStaticPartialByIdList(orderChild);
        return updateStaticPartialByIdList;
    }

    /**
     * 通过id列表更新(局部更新)(更新内容不相同)
     * 
     * @param orderChild
     * @return
     * @throws SQLException
     */
    @Override
    public int updateChangePartialByIdList(OrderChild orderChild) {
        int updateChangePartialByIdList = orderChildDaoImpl.updateChangePartialByIdList(orderChild.getOrderChilds());
        return updateChangePartialByIdList;
    }

    /**
     * 通过id查询
     * 
     * @param id
     * @return
     * @throws SQLException
     */
    @Override
    public OrderChild findById(Integer id) {
        OrderChild findById = orderChildDaoImpl.findById(id);
        return findById;
    }

    /**
     * 通过id列表查询
     * 
     * @param ids
     * @return
     * @throws SQLException
     */
    @Override
    public ArrayList<OrderChild> findByIdList(ArrayList<Integer> ids) {
        ArrayList<OrderChild> findByIdList = orderChildDaoImpl.findByIdList(ids);
        return findByIdList;
    }

    /**
     * 通过对象查询id列表
     * 
     * @param orderChild
     * @return
     * @throws SQLException
     */
    @Override
    public ArrayList<Integer> findIdByDto(OrderChild orderChild) {
        ArrayList<Integer> findIdByDto = orderChildDaoImpl.findIdByDto(orderChild);
        return findIdByDto;
    }

    /**
     * 清空数据(物理清空)
     * 
     * @throws SQLException
     */
    @Override
    public void clear() {
        orderChildDaoImpl.clear();
    }

    /**
     * 获取子订单信息(包含其他附加信息)
     * 
     * @param orderSn 订单编号
     * @return
     */
    @Override
    public OrderChild getInfoByOrderSn(String orderSn) {
        return orderChildDaoImpl.getInfoByOrderSn(orderSn);
    }

    /**
     * 租赁退款
     * 
     * @param orderChild
     * @return
     * @throws Exception 
     */
    @Override
    public int refundNew(OrderChild orderChild) throws Exception {
        synchronized (Lock.ORDER_STATUS) {
            return orderChildServiceImpl.refundNewGo(orderChild);
        }
    }

    @Transactional
    public int refundNewGo(OrderChild orderChild) throws Exception {
        int updatePartialById = 0;
        OrderChild findByOrderChildSn = orderChildDaoImpl.findByOrderChildSn(orderChild.getOrderChildSn());
        Order findById = orderDaoImpl.findById(findByOrderChildSn.getOrderId());
        if (StringUtil.isBlankObject(findById)) {
            throw new TransException("主订单不存在！");
        }
        if (findById.getStatus() != EOrderStatus.RETU_YES.getCode()) {
            throw new TransException("请先关闭订单或等待订单完成！");
        }
        if (StringUtil.isBlankObject(findByOrderChildSn)) {
            throw new TransException("订单不存在！");
        }
        if (findByOrderChildSn.getOrderTotal().subtract(orderChild.getOrderTotal()).doubleValue() < 0) {
            throw new TransException("订单退款金额大于订单金额！");
        }
        if (findByOrderChildSn.getIsPay() == EPayStatus.NO.getCode()) {
            throw new TransException("订单未支付！");
        }
        Integer isRefunds = findByOrderChildSn.getIsRefunds();
        if (isRefunds == ERefundsStatus.YES.getCode() || isRefunds == ERefundsStatus.ING.getCode()) {
            throw new TransException("一个订单只能退款一次！");
        }
        OrderChild ord = new OrderChild();
        ord.updateInit();
        ord.setId(findByOrderChildSn.getId());
        ord.setStatus(EOrderChildStatus.PAYMENT_YES.getCode());
        ord.setRefundTotal(orderChild.getOrderTotal());
        ord.setIsRefunds(ERefundsStatus.ING.getCode());
        updatePartialById = orderChildDaoImpl.updatePartialById(ord);
        // 关闭订单
        if (updatePartialById < 1) {
            throw new TransException("修改订单失败！");
        }
        // 获取微信接口参数
        Map<String, String> config = SystemParamUtil.gets();
        String mchid = config.get(WxConstant.MCHID_CACHE_NAME);
        String serialNo = config.get(WxConstant.CA_SERIALNO_CACHE_NAME);

        // 拼装参数
        WxPamAmount wxPamAmount = new WxPamAmount();
        wxPamAmount.setCurrency(WxCurrencyType.CNY);
        wxPamAmount.setRefund(ArithUtil.bigDollarToIntPenny(ord.getRefundTotal()));
        wxPamAmount.setTotal(ArithUtil.bigDollarToIntPenny(findByOrderChildSn.getOrderTotal()));
        WxParamV3 wxParam = new WxParamV3();
        wxParam.setAmount(wxPamAmount);
        wxParam.setNotifyUrl(WxConstant.NOTIFY_URL_PAY_CANCEL_GO_ON_INITIATIVE);
        wxParam.setOutRefundNo(GUIDUtil.generateGuid());
        wxParam.setOutTradeNo(findByOrderChildSn.getOrderChildSn());
        // 调用退款接口
        IJPayHttpResponse v3 =
            WxPayApi.v3(RequestMethod.POST, WxDomain.CHINA.getType(), WxApiType.DOMESTIC_REFUNDS.getType(), mchid,
                serialNo, null, WxUtil.PRIVATE_KEY, JsonUtil.objectToJson(wxParam));
        // 获取响应结果
        WxResponseV3 jsonToObject = JsonUtil.jsonToObject(v3.getBody(), WxResponseV3.class);
        String status = jsonToObject.getRefundStatus();
        if (!"SUCCESS".equals(status) && !"PROCESSING".equals(status)) {
            throw new TransException("退款失败！");
        }
        return updatePartialById;
    }

    /**
     * 获取子订单信息
     * 
     * @param orderSn 订单编号
     * @return
     */
    @Override
    public OrderChild findByOrderChildSn(String orderChildSn) {
        return orderChildDaoImpl.findByOrderChildSn(orderChildSn);
    }

}